package com.gamefx.engine1.managers
{
	import flash.events.TimerEvent;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	import flash.utils.getTimer;

	internal class TimerManagerImpl implements ITimerManager
	{
		private static var instance:TimerManagerImpl;
		private var timer:Timer;
		private var runnings:Object;
		private var accumulator:uint;
		private var count:uint;

		public function TimerManagerImpl()
		{
			super();

			if (instance != null)
			{
				throw new Error("Instance already exists.");
			}

			instance = this;
			runnings = {};
			timer = new Timer(17);
			timer.addEventListener(TimerEvent.TIMER, timer_timerHandler);
		}

		public static function getInstance():TimerManagerImpl
		{
			if (!instance)
			{
				instance = new TimerManagerImpl();
			}

			return instance;
		}




		public function setTimeout(closure:Function, delay:Number, arguments:Array):uint
		{
			return addRunning( new Running(closure, delay, arguments) );
		}

		public function clearTimeout(id:uint):void
		{
			removeRunning(id);
		}

		public function setInterval(closure:Function, delay:Number, arguments:Array):uint
		{
			return addRunning( new Running(closure, delay, arguments, 0) );
		}

		public function clearInterval(id:uint):void
		{
			removeRunning(id);
		}
		
		
		

		private function addRunning(running:Running):uint
		{
			accumulator++;
			count++;
			running.id = accumulator;
			runnings[accumulator] = running;
			
			if (!timer.running)
			{
				timer.start();
			}
			
			return accumulator;
		}
		
		private function removeRunning(id:uint):void
		{
			if (runnings.hasOwnProperty(id))
			{
				delete runnings[id];
				count--;
				
				if (count <= 0)
				{
					timer.reset();
					accumulator = 0;
				}
			}
		}
		
		private function timer_timerHandler(event:TimerEvent):void
		{
			var currentTime:int = getTimer();
			var running:Running;
			
			for (var id:String in runnings)
			{
				running = runnings[id];
				
				if (currentTime - running.timeFlag >= running.delay)
				{
					running.closure.apply(null, running.arguments);
					
					if (running.repeatCount > 0)
					{
						running.currentCount++;
						if (running.currentCount >= running.repeatCount)
						{
							removeRunning(running.id);
							continue;
						}
					}
					
					running.timeFlag = currentTime;
				}
			}
		}
	}
}

class Running
{
	/**
	 * 标识
	 */
	public var id:uint;
	
	/**
	 * 要执行的函数的名称
	 */
	public var closure:Function;

	/**
	 * 执行函数之前的延迟时间
	 */
	public var delay:Number;

	/**
	 * 传递给 closure 函数的可选参数列表
	 */
	public var arguments:Array;

	/**
	 * 设置的closure运行总次数（如果重复计数设置为 0，则将持续不断运行，直至调用了 stop() 方法或程序停止。）
	 */
	public var repeatCount:int;

	/**
	 * 时间戳
	 */
	public var timeFlag:int;
	
	/**
	 * closure已累计执行的次数
	 */
	public var currentCount:int;
	
	
	public function Running(closure:Function, delay:Number, arguments:Array, repeatCount:int = 1)
	{
		this.closure = closure;
		this.delay = delay;
		this.arguments = arguments;
		this.repeatCount = repeatCount;
	}
}
